package com.oromwin.repos.thread;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import com.oromwin.repos.client.ReposSocketClient;
import com.oromwin.repos.common.ReposException;
import com.oromwin.repos.common.helper.FSHelper;
import com.oromwin.repos.data.FileTable;

public class MultiThreadedFileUpload {
    private static boolean createFile = false;
    private static boolean createVolume = false;
    private static boolean createMedia = false;
    private static boolean uploadFile = false;
    private static boolean downloadFile = false;
    private static boolean deleteFile = false;

    private static final ReposSocketClient client = new ReposSocketClient("localhost", 5000);
    private static String volumeId = "";
    private static String mediaId = "";

    public static void main(String[] args) {
        try {
            int runCount = 1;
            int fileCount = 1;
            int fileSize = 1024 * 1024 * 5; // 5mb
            FileManager manager = new FileManager(new File("D:\\Repository\\Temp"), fileCount, fileSize);
            if (createFile) manager.create();

            if (createVolume) volumeId = client.createVolume("libeka");

            if (createMedia) {
                File mediaPath = new File("D:\\Repository\\ReposRoot");
                long mediaMaxBytes = 1024 * 1024 * 1024; // 1gb
                mediaId = client.createMedia(volumeId, mediaPath, mediaMaxBytes);
            }

            if (uploadFile) {
                for (int i = 0; i < runCount; ++i) {
                    new FileUploader(manager, client, volumeId).start();
                }
            }

            if (downloadFile) {
                for (int i = 0; i < runCount; ++i) {
                    new FileDownloader(manager, client, mediaId).start();
                }
            }

            if (deleteFile) manager.delete();

        } catch (ReposException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();

        }
    }
}

class FileManager {
    private static File filePath = new File("C:\\");
    private static int fileCount = 10;
    private static long fileSize = 1024 * 1024 * 5; // 5mb
    public FileManager() {
    }
    public FileManager(File path) {
        filePath = path;
    }
    public FileManager(File path, int count, long size) {
        filePath = path;
        fileCount = count;
        fileSize = size;
    }
    public File createFileName(int i) {
        return new File(filePath + File.separator + "fileName." + i);
    }
    public File readFileName(int i) {
        return new File(filePath + File.separator + "readName." + i);
    }
    public int getFileCount() {
        return fileCount;
    }
    public long getFileSize() {
        return fileSize;
    }
    public void create() throws IOException {
        for (int i = 0; i < fileCount; ++i) {
            int off = 0;
            int len = 4096;
            int write = 0;
            byte[] b = new byte[len];
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(createFileName(i)));
            while (write < fileSize) {
                bos.write(b, off, len);
                write += len;
            }
            bos.flush();
            bos.close();
        }
    }
    public void delete() throws ReposException {
        for (int i = 0; i < fileCount; ++i) {
            FSHelper.rm(createFileName(i));
        }
    }
}

class FileUploader extends Thread {
    private FileManager manager;
    private ReposSocketClient client;
    private String volumeId;
    public FileUploader(FileManager _manager, ReposSocketClient _client, String _volumeId) {
        manager = _manager;
        client = _client;
        volumeId = _volumeId;
    }
    public void run() {
        int fileCount = manager.getFileCount();
        for (int i = 0; i < fileCount; ++i) {
            File filePath = manager.createFileName(i);
            System.out.println("Uploading '" + filePath + "' file...");
            try {
                String fileId = client.createFile(volumeId, filePath);
                System.out.println("Upload '" + fileId + "' Completed.");
            } catch (ReposException e) {
                e.printStackTrace();
            }
        }
    }
}

class FileDownloader extends Thread {
    private FileManager manager;
    private ReposSocketClient client;
    private String mediaId;
    public FileDownloader(FileManager _manager, ReposSocketClient _client, String _mediaId) {
        manager = _manager;
        client = _client;
        mediaId = _mediaId;
    }
    public void run() {
        List fileList;
        try {
            fileList = client.listMedia(mediaId);
            Iterator fi = fileList.iterator();
            int i = 0;
            while (fi.hasNext()) {
                FileTable ft = (FileTable) fi.next();
                String fileId = ft.getFileId();
                System.out.println("Downloading '" + fileId + "' file...");
                File fileName = manager.readFileName(i);
                client.readFile(fileId, fileName);
                i += 1;
                System.out.println("Download '" + fileName.getCanonicalPath() + "' Completed.");
            }
        } catch (ReposException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
